package com.gopay.scheduler.job;

import com.gopay.common.constants.trans.DepositFundSettleOpType;
import com.gopay.common.domain.cps.transfer.Tran02200VO;
import com.gopay.common.domain.cps.vo.CPSResponse;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.util.DateUtils;
import com.gopay.cron.web.util.CallCPSUtil;
import com.gopay.scheduler.GopayBaseJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

/**
 * 发起资金存管交易
 * Created by zhaojt on 2017/1/18.
 */
public class Tran02200Job extends GopayBaseJob{

    private Logger logger = LoggerFactory.getLogger(Tran02200Job.class);

    @Resource(name = "commonQueryDAO")
    private CommonQueryDAO commonQueryDAO;

    public void doJobInternal() {
        logger.info("存管资金Job开始...");
        try{
            long totalStart = System.currentTimeMillis();

            List<Object[]> rows = calculateTrans();

            if(rows != null){
                logger.info("共计算出待处理交易 " + rows.size() + " 笔。");
            }

            for(Object[] row : rows) {
                Tran02200VO tran02200VO = new Tran02200VO();

                tran02200VO.setAcctId((String)row[0]);
                tran02200VO.setPayCustId((String)row[1]);
                tran02200VO.setTxnAmt((BigDecimal)row[2]);
                tran02200VO.setOpType(DepositFundSettleOpType.APPLY);
                try {
                    tran02200VO.setClientIp(InetAddress.getLocalHost().toString());
                }catch (UnknownHostException e1){
                    logger.info("获取客户端IP失败：" + e1);
                    tran02200VO.setClientIp("");
                }

                callCps(tran02200VO);
            }

            long totalEnd = System.currentTimeMillis() - totalStart;
            logger.info("存管资金Job结束 ： 总耗时 = " + totalEnd);
        }catch (Exception e){
            logger.error("资金存管交易定时任务异常",e);
        }

    }

    private List<Object[]> calculateTrans(){
        Date date = new Date();
        String T = DateUtils.format(date, DateUtils.FILEDATE_PATTERM);

        Date gopayTxntm = DateUtils.add(date, Calendar.DATE, -30);//30天前
        logger.info("资金存管SQL 入参 ： T = {}, gopayTxntm = {}", T, gopayTxntm);

        StringBuilder sb = new StringBuilder();

        sb.append(" SELECT");
        sb.append(" MO.MAIN_RECV_ACCT ACCT,");
        sb.append(" AAM.CUST_ID, ");
        sb.append(" SUM(MO.MER_TXN_AMT) AMT");
        sb.append(" FROM CPS_GEN_RECEIPT_ORDER RO");
        sb.append(" LEFT JOIN CPS_GEN_MAIN_ORDER MO");
        sb.append(" ON RO.GOPAY_ORDER_ID = MO.GOPAY_ORDER_ID");
        sb.append(" LEFT JOIN ACPS_ACCT_MAST AAM");
        sb.append(" ON MO.MAIN_RECV_ACCT = AAM.ACCT_ID");
        sb.append(" WHERE RO.DF_SETTLE_TIME = :start ");
        sb.append(" AND MO.GOPAY_INT_TXN_CD = '00100'");
        sb.append(" AND AAM.PROD_CODE = 'DFSA'");
        sb.append(" AND MO.GATEWAY_SOURCE = '17'");
        sb.append(" AND MO.TXN_STA_CD = '20000'");
        sb.append(" AND MO.GOPAY_TXN_TM > :gopayTxntm");
        sb.append(" GROUP BY MO.MAIN_RECV_ACCT, AAM.CUST_ID ");

        Map params = new HashMap();
        params.put("start", T);
        params.put("gopayTxntm", gopayTxntm);

        List<Object[]> rows = commonQueryDAO.findBySql(sb.toString(), params);

        return rows;
    }

    private void callCps(Tran02200VO vo){
        long start = System.currentTimeMillis();

        logger.info("资金存管交易调用cps入参 vo = {}", vo);

        logger.info("校验是否重复发起资金存管交易：");

        if(!checkRecall(vo)){
            logger.error("存在重复交易");
            return ;
        }

        try {
            CPSResponse cpsResponse = CallCPSUtil.callByVOTicket(vo);
            logger.info("资金存管交易调用cps出参 resp = {}", cpsResponse);
        } catch (GopayException e) {
            logger.error("资金存管交易调用cps失败 errCode = {}, errMsg = {}", e.getErrCode(), e.getErrMsg());
            logger.error("资金存管交易调用cps失败 ex = {}", e);
        } finally {
            long time = System.currentTimeMillis() - start;
            logger.info("调用cps单次耗时 ：" +  time);
        }
    }

    /**
     * 校验重复调用
     * @param vo
     */
    private boolean checkRecall(Tran02200VO vo){
        StringBuilder sb = new StringBuilder();
        sb.append(" select * from cps_gen_main_order t ");
        sb.append(" where t.gopay_int_txn_cd = '02200' ");
        sb.append(" and t.pay_acct = :payAcct ");
        sb.append(" and to_char( t.GOPAY_TXN_TM,'yyyyMMdd') = :today ");

        HashMap<String, Object> param = new HashMap<>();
        param.put("payAcct", vo.getAcctId());
        param.put("today", DateUtils.getCurrDate(DateUtils.FILEDATE_PATTERM));

        List<Object[]> result = commonQueryDAO.findBySql(sb.toString(), param);

        return ( result == null || result.size() == 0 ) ;
    }
}
